# Drag and drop module
# 2009 NIXON Development Corporation.

import wx, thread, time, Queue, cPickle
import format, local

class scrollTimer(wx.Timer):
	def __init__(self, prnt):
		wx.Timer.__init__(self)
		self.prnt = prnt
		self.dir = 1
		
	def Notify(self):
		if self.dir == 0: self.prnt.box.ScrollList(0, -16)
		else: self.prnt.box.ScrollList(0, 16)
		
class springTimer(wx.Timer):
	def __init__(self, prnt):
		wx.Timer.__init__(self)
		self.prnt = prnt
		
	def Notify(self):
		if self.intPos <> -1 and self.intPos == self.prnt.intPos:
			self.prnt.delayTraverse(self.intPos)
		
class listDrop(wx.PyDropTarget):
	intPos = -1

	def _process(self):
		fcn, args, kwargs = self.q.get()
		fcn(*args, **kwargs)

	def CallAfter(self, fcn, *args, **kwargs):
		self.q.put((fcn, args, kwargs))
		wx.CallAfter(self._process)

	def __init__(self, prnt, box):
		wx.DropTarget.__init__(self)
		doc = wx.DataObjectComposite()
		doc.fileObject = wx.FileDataObject()
		doc.listObject = wx.CustomDataObject('ListCtrlItems')
		doc.Add(doc.fileObject)
		doc.Add(doc.listObject)
		self.SetDataObject(doc)
		self.doc = doc
		self.prnt = prnt
		self.box = box
		self.q = Queue.Queue()
		self.stimer = scrollTimer(self)
		self.sltimer = springTimer(self)
		
	def OnEnter(self, x, y, default):
		self.lstItemStates = []
		for item in range(0, self.box.GetItemCount()):
			self.lstItemStates.append(self.box.GetItemState(item, wx.LIST_STATE_SELECTED))
			
		return default
		
	def OnDragOver(self, x, y, default):
		try:
			compare = self.box.GetNextItem(-1, state=wx.LIST_STATE_DROPHILITED)
			result = self.box.HitTest((x,y))
			
			if (result[0] <> -1) and (result[0] <> compare):
				self.setOriginalStates()
				
				sel = self.box.GetItem(result[0]).GetText()
				pwf = self.box.Label + '/' + sel
				if self.box.blLocal:
					tst = local.getType(pwf)
				else:
					tst = self.prnt.hdlFrame.dirList.getType(pwf)
				
				if tst > 0:
					self.box.SetItemState(result[0], wx.LIST_STATE_DROPHILITED, wx.LIST_MASK_STATE)
					if result[1] == wx.LIST_HITTEST_ONITEMLABEL or result[1] == wx.LIST_HITTEST_ONITEMICON \
						or result[1] == 129:
						self.intPos = result[0]
						self.sltimer.intPos = result[0]
						self.sltimer.Start(1000, True)
				else:
					self.intPos = -1
					
			h = self.box.GetSize()[1]
			if y >= h - 8:
				self.stimer.dir = 1
				self.stimer.Start(50, True)
			elif y <= 8:
				self.stimer.dir = 0
				self.stimer.Start(50, True)
			
		except: pass

		return default
			
	def delayTraverse(self, intPos):
		if self.intPos == intPos:
			sel = self.box.GetItem(self.intPos).GetText()
			pwf = self.box.Label + '/' + sel
			self.CallAfter(self.prnt.removeListBox, self.box.Number)
			self.CallAfter(self.prnt.addListBox, sel)
			if self.box.blLocal:
				self.CallAfter(self.prnt.hdlFrame.UpdateLocal, pwf)
			else:
				self.CallAfter(self.prnt.hdlFrame.UpdateList, pwf)
			self.intPos = -1
			self.prnt.hdlFrame.Refresh()
		
	def setOriginalStates(self):
		try:
			for item in range(0, self.box.GetItemCount()):
				self.box.SetItemState(item, self.lstItemStates[item], wx.LIST_MASK_STATE)
		except Exception, e: pass
		
	def OnLeave(self):
		self.setOriginalStates()
		self.blOver = False
		self.intPos = -1
		return wx.DropTarget.OnLeave(self)
		
	def OnData(self, x, y, res):
		if not self.GetData(): return
		tst = self.doc.GetReceivedFormat()
		lstFiles = []
		
		if tst == wx.DataFormat(wx.DF_FILENAME):
			if self.box.blLocal:
				self.OnLeave()
				return

			tpFiles = self.doc.fileObject.GetFilenames()
			pwd = format.getNameFromPath(tpFiles[0], True)
			
			for name in tpFiles:
				try:
					pwf = format.getNameFromPath(name)
					lstFiles.append(pwf)
				except IOError, error:
					dlg = wx.MessageDialog(None, 'Error opening file\n' + str(error))
					dlg.ShowModal()
				except UnicodeDecodeError, error:
					dlg = wx.MessageDialog(None, 'Cannot open non ascii files\n' + str(error))
					dlg.ShowModal()
					
			folderHighlighted = self.box.GetNextItem(-1, state=wx.LIST_STATE_DROPHILITED)
			if folderHighlighted <> -1:
				pwf = self.box.Label + '/' + self.box.GetItem(folderHighlighted).GetText()
				self.prnt.hdlFrame.dirList.doPath(pwf, self.prnt.hdlFrame.mFTP, True)
				print(pwf)
				box = None
			else:
				pwf = ''
				box = self.box
				
		elif tst.GetId() == 'ListCtrlItems':
			ldata = self.doc.listObject.GetData()
			l = cPickle.loads(ldata)
			box = None
			pwf = self.box.Label
			pwd = l[0][0]
			for x in range(1, len(l)):
				lstFiles.append(l[x][0])
			self.q.queue.clear()
				
		if self.intPos > -1:
			pwf += '/' + self.box.GetItem(self.intPos).GetText()
				
		self.prnt.hdlFrame.mFTP.transfer(pwd, lstFiles, self.prnt.hdlFrame, not(self.box.blLocal), box, pwf)
		self.OnLeave()
